package com.hunt.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hunt.dao.AddressInfoMapper;
import com.hunt.dao.FinancialDataMapper;
import com.hunt.dao.TransactionCalendarMapper;
import com.hunt.model.app.FinancialDataInfo;
import com.hunt.model.app.StockAllMessage;
import com.hunt.model.app.TransactionCalendar;
import com.hunt.model.entity.*;
import com.hunt.service.StockAllMessageService;
import com.hunt.util.SeasonEnum;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service
public class StockAllMessageServiceImpl implements StockAllMessageService {
    @Resource
    private RedisTemplate stringredisTemplate;
    @Autowired
    private MongoTemplate stockMinKLineMongoTemplate;
    @Autowired
    private MongoTemplate stockDayMongoTemplate;

    @Override
    public StockAllMessage getStockallmessage(String code,boolean  istransaction) throws ParseException {
        Object obj = stringredisTemplate.opsForHash().get("Real_time_Stock_Data", code);
        Object obj1 = stringredisTemplate.opsForHash().get("Price_Limit", code);
        JSONObject jo = JSON.parseObject((String) obj);
        JSONObject priceLimit = JSON.parseObject((String) obj1);
        double newprice = 0.0;
        try {
            newprice = jo.getDouble("newPrice");
        } catch (Exception e) {

        }

        double high = 0.0;
        try {
            high = jo.getDouble("high");
        } catch (Exception e) {
        }
        double low = 0.0;
        try {

            low = jo.getDouble("low");
        } catch (Exception e) {

        }
        double open = 0.0;
        try {

            open = jo.getDouble("open");
        } catch (Exception e) {

        }
        double Preclose = 0.0;
        try {

            Preclose = jo.getDouble("preClose");
        } catch (Exception e) {

        }
        double vol = 0.0;
        try {

            vol = jo.getDouble("vol");
        } catch (Exception e) {

        }
        double turnover = 0.0;
        try {

            turnover = jo.getDouble("money");
        } catch (Exception e) {

        }
        double avgprice = 0.0;
        try {

            avgprice = turnover / vol/100;
        } catch (Exception e) {

        }
        double downlimit = 0.0;
        try {

            downlimit = priceLimit.getJSONObject("table").getDouble("downLimit");
        } catch (Exception e) {

        }
        double upperlimit = 0.0;
        try {

            upperlimit = priceLimit.getJSONObject("table").getDouble("upperLimit");
        } catch (Exception e) {

        }
        double qrr = 0.0;
        try {
            if (jo.getDouble("qrr") != null) {
                qrr = jo.getDouble("qrr");
            }
        } catch (Exception e) {

        }
        Object obj2 = stringredisTemplate.opsForHash().get("Stock_Base_Message", code);
        JSONObject jo2 = JSON.parseObject((String) obj2);
        double floatsharesstock = 0.0;
        try {
            if (jo2.getFloat("floatShares") != null) {
                floatsharesstock = jo2.getDouble("floatShares")*10000;
            }
        } catch (Exception e) {

        }
        double floatsharesstockvol = 0.0;
        try {
           floatsharesstockvol=floatsharesstock*newprice;
        } catch (Exception e) {

        }
        double totalsharestock = 0.0;
        try {
            if (jo2.getFloat("totalShares") != null) {
                totalsharestock = jo2.getDouble("totalShares")*10000;
            }
        } catch (Exception e) {

        }
        /* 换手率 （成交量）/流通股数*/
        double handchange = 0.0;
        try {
            if (vol != 0.0 && floatsharesstock != 0.0) {
                handchange = (vol *100 / floatsharesstock);
            }
        } catch (Exception e) {

        }
        double mv = 0.0;
        try {
            if (totalsharestock != 0.0 && newprice != 0.0) {
                mv = totalsharestock * newprice;
            }
        } catch (Exception e) {

        }
        double pe = 0.0;
        try {
           pe=getpe(jo2.getDouble("n_income_attr_p"),jo2.getString("end_date").substring(4,8),mv);
        } catch (Exception e) {

        }
        StockAllMessage stockAllMessage = new StockAllMessage(newprice, avgprice, high, low, open, Preclose, vol, turnover, qrr, floatsharesstock, floatsharesstockvol, totalsharestock, mv, pe, downlimit, upperlimit, handchange);
//        StockAllMessage stockAllMessage=new StockAllMessage();
        return stockAllMessage;

    }

    /*   量比 （现成交总手数/现累计开市时间（分））/过去五日每分钟交易量*/
    private double getqrr(double vol, String code, String time,boolean  istransaction) throws ParseException {
        Query query = new Query();
        query.addCriteria(Criteria.where("vol").ne(0));
        int timecut=getminutecut(time);
        // 非交易日时默认开盘时间超过开盘的240分钟,就当成250分钟吧。
        if(!istransaction){
            timecut=250;
        }
        //发布日期排序获取过去五日数据，需要的数据库交易结束才落盘
        if(timecut>=240){
            query.with(new Sort(Sort.Direction.DESC, "_id")).skip(1);
        }
        else {
            query.with(new Sort(Sort.Direction.DESC, "_id"));
        }
        Query query1 = new Query();
        //发布日期排序获取当日数据
        query1.with(new Sort(Sort.Direction.DESC, "_id")).limit(1);
        List<DayKLine> d1 = stockDayMongoTemplate.find(query,DayKLine.class, code);
        List<MinKLine> donly=stockMinKLineMongoTemplate.find(query1,MinKLine.class, code);
        List<Double> li = new ArrayList<>();
        int needday=5;
        if(d1.size()<5){
            needday=d1.size();
        }
        for (int i = 0; i < needday; i++) {
            li.add(Double.valueOf(d1.get(i).getVol()));
        }
        //获取过去五日总成交量
        int totalvol = 0;
        for (int i = 0; i < li.size(); i++)
        {
                totalvol += li.get(i);
        }
        //获取现成交总手数
        vol=donly.get(0).getEndVol();
        if (timecut != 0) {
            double result = vol / getminutecut(time) / (totalvol / (needday*241));
            return result;
        } else {
            return 0.0;
        }

    }

    private  int getminutecut(String time) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        Date date = sdf.parse(time);
        long thistime = date.getTime();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 9);
        calendar.set(Calendar.MINUTE, 30);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        long amopen = calendar.getTimeInMillis();
        //获取当日上午开盘时间戳
        calendar.set(Calendar.HOUR_OF_DAY, 11);
        calendar.set(Calendar.MINUTE, 30);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        long amclose = calendar.getTimeInMillis();
        //获取当日上午收盘时间戳
        calendar.set(Calendar.HOUR_OF_DAY, 13);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        long pmopen = calendar.getTimeInMillis();
        //获取当日下午开盘时间戳
        calendar.set(Calendar.HOUR_OF_DAY, 15);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        long pmclose = calendar.getTimeInMillis();
        //上午交易期间
        if (thistime > amopen && thistime < amclose) {
            return (int) ((thistime - amopen) / 60 / 1000);
        }
        if (thistime >= pmopen && thistime < pmclose) {
            return (int) ((thistime - pmopen) / 60 / 1000 + 120);
        }
        if (thistime >= amclose && thistime < pmopen) {
            return (int) ((amclose - amopen) / 60 / 1000);
        }
        if (thistime >= pmclose) {
            return 240;
        }
        return 0;
    }
    private double  getpe(double income,String time,double mv){
        double seasonincome=income/ SeasonEnum.getSeason(time)*4;
        return   mv/seasonincome;
    }

}
